home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BCI NET
/
BCI NET Dec 94.iso
/
archives
/
applications
/
wp
/
ged11.lha
/
Install
/
data
/
main
/
GoldED
/
API
/
rexx
/
main.c
next >
Wrap
C/C++ Source or Header
|
1994-08-12
|
12KB
|
406 lines
/* -----------------------------------------------------------------------------
GoldED API client example code, ©1994 Dietmar Eilert. Dice:
dcc main.c -// -mRR -r -proto -2.0 -o ram:rexx
The following code demonstrates how to add additional internal commands to
GoldED using a client. After having installed this client using GoldED's API
requester you may use the following additional commands within menus, macros or
in the command requester:
o DISPLAYBEEP (flash screen)
o ABOUT
The following example uses synchronous ARexx communication: Requests are
PutMsg()'ed to GoldED's port, followed by a WaitPort() to get the editor's
response. This works fine since we need no ARexx communication after the API
link has been established. If there were ARexx communication AFTER the link has
been established (i.e. after sending the 'API PORT=...' command to register
with GoldED), we would have to use an asynchronous design beeing capable of
answering incoming API messages while waiting for completion of ARexx requests
sent to GoldED.
FRANÇAIS
Le code suivant montre comment ajouter des commandes internes supplémentaires à
GoldED, en utilisant un client. Après avoir installé ce client en utilisant la
requête API de GoldED, vous pouvez utiliser une des commandes supplémentaires
suivantes dans les menus, les macros ou dans la requête de commande:
o DISPLAYBEEP (flasher l'écran)
o ABOUT
Cet exemple utilise la communication ARexx synchrone: les requêtes sont
PutMsg()'ées sur le port de GoldED, suivies d'un WaitPort() pour avoir la
réponse de l'éditeur. Ceci fonctionne très bien comme nous n'avons pas besoin
de communications ARexx après l'établissement de la liaison API (c-à-d après
l'envoi de la commande 'API PORT=...' pour s'enregistrer à GoldED), nous
aurions dû utiliser un système asynchrone étant capable de répondre aux
messages API arrivants, tout en attendant la fin des requêtes ARexx envoyées à
GoldED.
------------------------------------------------------------------------------
*/
/// "includes"
#define Prototype extern
#include <exec/exec.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <intuition/intuition.h>
#include <rexx/errors.h>
#include <rexx/rxslib.h>
#include <utility/tagitem.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/rexxsyslib_protos.h>
#include "golded:api/include/golded.h"
Prototype void main(int, char **);
Prototype void HandleAPI(char *);
Prototype void Dispatch(struct APIMessage *);
Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
Prototype LONG CommandBeep (ULONG *, struct APIMessage *);
Prototype LONG CommandAbout(ULONG *, struct APIMessage *);
///
/// "main"
void
main(int argc, char **argv)
{
const char *version = "$VER: rexx 1.3 (" __COMMODORE_DATE__ ")";
if (argc == 2)
HandleAPI(argv[1] + 5);
else
puts("syntax error: rexx HOST=<host>");
exit(0);
}
///
/// "API management"
/* --------------------------------- HandleAPI ---------------------------------
Register with GoldED & handle incoming API messages.
S'enregistrer à GoldED & gérer les messages API arrivants.
*/
void
HandleAPI(host)
char *host;
{
struct MsgPort *replyPort;
if (replyPort = CreateMsgPort()) {
char command[255];
ULONG *result;
sprintf(command, "API PORT=%ld MASK=%ld", replyPort, API_CLASS_ROOT | API_CLASS_REXX);
if (result = SendRexxCommand(host, command, replyPort, NULL)) {
if (*result == RC_OK) {
BOOL active = TRUE;
do {
struct APIMessage *apiMsg, *nextMsg;
// API messages might already have arrived since SendRexxCommand() only pulls one message of the port
while (!(apiMsg = (struct APIMessage *)GetMsg(replyPort)))
WaitPort(replyPort);
do {
for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
if (nextMsg->api_State == API_STATE_NOTIFY) {
switch (nextMsg->api_Class) {
case API_CLASS_ROOT:
switch (nextMsg->api_Action) {
case API_ACTION_DIE:
active = FALSE;
break;
case API_ACTION_INTRODUCE:
static struct TagItem tags[] = {
API_Client_Name, "rexx",
API_Client_Copyright, "©1994 Dietmar Eilert",
API_Client_Purpose, "API client example code",
API_Client_Template, "DISPLAYBEEP",
API_Client_Template, "ABOUT",
TAG_DONE
};
nextMsg->api_Data = tags;
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
break;
case API_CLASS_REXX:
switch (nextMsg->api_Action) {
case API_ACTION_COMMAND:
Dispatch(nextMsg);
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
break;
default:
nextMsg->api_Error = API_ERROR_UNKNOWN;
}
}
}
ReplyMsg((struct Message *)apiMsg);
} while (apiMsg = (struct APIMessage *)GetMsg(replyPort));
} while (active);
}
}
DeleteMsgPort(replyPort);
}
}
///
/// "dispatcher"
/* --------------------------------- Dispatch ----------------------------------
Dispatch incoming command: examine command string (command part is uppercase
already), look for handler function related to command, parse arguments (if
command supports arguments), call handler.
Dispatcher les commandes arrivants: examiner la chaîne de la commande (la
partie commande est déjà en majuscules), rechercher des fonctions de gestion se
rapportant à la commande, analyser les arguments (si la commande gère des
arguments), appeler le gestionnaire.
*/
void
Dispatch(apiMsg)
struct APIMessage *apiMsg;
{
struct RDArgs *rdArgs, *args;
if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
static char buffer[1024];
// table of supported commands, associated handlers & template strings
// table des commandes gérées, chaînes des handlers & template associées
static struct parser { char *command; LONG (*handler)(ULONG *, struct APIMessage *); char *template; } parser[] = {
"DISPLAYBEEP", (APTR)CommandBeep, NULL,
"ABOUT", (APTR)CommandAbout, NULL,
NULL
};
ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
struct APIRexxNotify *notify = (struct APIRexxNotify *)apiMsg->api_Data;
// make LF-terminated copy of command string (required by dos/readArgs):
// créer une copie terminée par LF de la chaîne de commande (requise par dos/readArgs):
strcpy(buffer, notify->arn_Command);
strcat(buffer, "\12");
for (n = 0; parser[n].command; ++n) {
if (!memcmp(buffer, parser[n].command, strlen(parser[n].command))) {
// tell GoldED that message has been consumed by us:
// Dire à GoldED que le message a été utilisé par nous:
apiMsg->api_State = API_STATE_CONSUMED;
char *arguments = buffer + strlen(parser[n].command);
rdArgs->RDA_Source.CS_Buffer = arguments;
rdArgs->RDA_Source.CS_Length = strlen(arguments);
rdArgs->RDA_Source.CS_CurChr = 0;
rdArgs->RDA_DAList = NULL;
rdArgs->RDA_Buffer = NULL;
if (parser[n].template) {
if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
notify->arn_RC = (*parser[n].handler)(argArray, apiMsg);
FreeArgs(args);
}
else {
static char errorText[81];
notify->arn_RC = RC_WARN;
notify->arn_CommandError = errorText;
Fault(IoErr(), "IoErr()", errorText, 80);
}
}
else
notify->arn_RC = (*parser[n].handler)(argArray, apiMsg);
}
}
FreeDosObject(DOS_RDARGS, rdArgs);
}
}
/* -------------------------------- CommandBeep --------------------------------
DISPLAYBEEP
*/
LONG
CommandBeep(argArray, apiMsg)
ULONG *argArray;
struct APIMessage *apiMsg;
{
DisplayBeep(0);
return(RC_OK);
}
/* ------------------------------- CommandAbout --------------------------------
ABOUT (open a requester on GoldED's screen)
ABOUT (ouvre une requête sur l'écran GoldED)
*/
LONG
CommandAbout(argArray, apiMsg)
ULONG *argArray;
struct APIMessage *apiMsg;
{
struct EasyStruct about = {sizeof(struct EasyStruct), 0, "Info", "Just some API client example code", "OK" };
EasyRequestArgs(apiMsg->api_WinInfo->Window, &about, NULL, NULL);
return(RC_OK);
}
///
/// "ARexx"
/* ---------------------------------- SendRexxCommand -------------------------
Send ARexx message & wait for answer. Return pointer to result or NULL.
Envoyer une commande ARexx et attendre une réponse. Retourne un pointeur sur le
résultat ou NULL.
*/
ULONG *
SendRexxCommand(port, cmd, replyPort, buffer)
char *cmd, *port, *buffer;
struct MsgPort *replyPort;
{
struct MsgPort *rexxport;
Forbid();
if (rexxport = FindPort(port)) {
struct RexxMsg *rexxMsg, *answer;
if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
static ULONG result;
rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
PutMsg(rexxport, &rexxMsg->rm_Node);
do {
WaitPort(replyPort);
if (answer = (struct RexxMsg *)GetMsg(replyPort))
result = answer->rm_Result1;
} while (!answer);
Permit();
if (answer->rm_Result1 == RC_OK) {
if (answer->rm_Result2) {
if (buffer)
strcpy(buffer, (char *)answer->rm_Result2);
DeleteArgstring((char *)answer->rm_Result2);
}
}
DeleteArgstring((char *)ARG0(answer));
DeleteRexxMsg(answer);
return(&result);
}
}
}
Permit();
return(NULL);
}
///